package com.mysql.engine.impl;

import com.mysql.bean.ClassInfo;
import com.mysql.bean.ConfigurationInfo;
import com.mysql.bean.GlobleConfig;
import com.mysql.constants.CostConstants;
import com.mysql.engine.AbstractEngine;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class DefaultEngine extends AbstractEngine {

	private static Logger logger = LoggerFactory.getLogger(DefaultEngine.class);


	private static final String SEPARATOR = File.separator;

	private ConfigurationInfo config;

	private Configuration configuration;

	/**
	 * java文件路径
	 */
	private static final String SRC_MAIN_JAVA = SEPARATOR + "src" + SEPARATOR + "main" + SEPARATOR + "java" + SEPARATOR;

	/**
	 * 资源文件路径
	 */
	private static final String SRC_MAIN_RESOURCE = SEPARATOR + "src" + SEPARATOR + "main" + SEPARATOR + "resources" + SEPARATOR;


	public DefaultEngine() {
		config = GlobleConfig.getGlobleConfig();
		configuration = AbstractEngine.getConfiguration();
	}

	/**
	 * 生成文件
	 *
	 * @param classInfo
	 * @param templateName 模板名
	 * @param moduleName   模块名
	 * @param classPrefix  文件名前缀
	 * @param classSuffix  文件名后缀
	 * @return void
	 * @Date 10:53 2024/9/27
	 * @since 2.3
	 */
	private void genClass(ClassInfo classInfo, String templateName, String moduleName, String classPrefix, String classSuffix, String packageName) {
		//文件名
		String fileName = classPrefix + classInfo.getTableAliasName() + classSuffix;

		//H:\cost-code-dev-all\cost-boot-starter-api\modules\cost-model\src\main\java\com\fw\cost\model\entity\researchCost\ResearchProjCostSummaryModel.java
		String filePath = config.getRootPath() + SEPARATOR + moduleName + SRC_MAIN_JAVA + packageName + SEPARATOR + fileName;
		logger.info("文件地址:{}", filePath);
		process(classInfo, templateName, filePath);
	}

	/**
	 * 生成资源文件
	 *
	 * @param classInfo
	 * @param templateName
	 * @param moduleName
	 * @param classPrefix
	 * @param classSuffix
	 * @return void
	 * @Date 11:26 2024/9/27
	 * @since 2.3
	 */
	private void genResourcesFile(ClassInfo classInfo, String templateName, String moduleName, String classPrefix, String classSuffix) {
		String packageName = config.getMapperPackageName().replace(CostConstants.MAPPER_XML_REPLACE_STR, "").replace(".", SEPARATOR);

		//文件名
		String fileName = classPrefix + classInfo.getTableAliasName() + classSuffix;
		//H:\cost-code-dev-all\cost-boot-starter-api\modules\cost-producer\src\main\resources\mapper\researchCost\ResearchProjCostSummaryMapper.xml
		String filePath = config.getRootPath() + SEPARATOR + moduleName + SRC_MAIN_RESOURCE + packageName + SEPARATOR + fileName;
		logger.info("文件地址:{}", filePath);
		process(classInfo, templateName, filePath);
	}

	/***
	 * FreeMarker 模板固定方法
	 * @param classInfo
	 * @param templateName
	 * @param filePath
	 */
	private void process(ClassInfo classInfo, String templateName, String filePath) {
		try {
			File file = new File(filePath);
			file.getParentFile().mkdirs();

			Writer writer = new FileWriter(new File(filePath));

			Template template = configuration.getTemplate(templateName);

			Map<String, Object> params = new HashMap<>(16);
			params.put("classInfo", classInfo);
			params.put("genConfig", config);

			try {
				//反射获取所有属性及值
				for (Field field : ConfigurationInfo.class.getDeclaredFields()) {
					field.setAccessible(true); // 允许访问私有字段
					params.put(field.getName(), field.get(config));
				}
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}


			template.process(params, writer);
			writer.flush();
			writer.close();
		} catch (IOException | TemplateException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 生成controller
	 */
	@Override
	public void genController(ClassInfo classInfo) {
		//模块名
		String moduleName = CostConstants.CONTROLLER_MODULE_NAME;
		String templateName = CostConstants.CONTROLLER_TEMPLATE_NAME;
		String classPrefix = CostConstants.CONTROLLER_CLASS_PREFIX;
		String classSuffix = CostConstants.CONTROLLER_CLASS_SUFFIX;
		String packageName = config.getControllerPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);
	}

	/**
	 * 生成service
	 */
	@Override
	public void genService(ClassInfo classInfo) {
		//模块名
		String moduleName = CostConstants.SERVICE_MODULE_NAME;
		String templateName = CostConstants.SERVICE_TEMPLATE_NAME;
		String classPrefix = CostConstants.SERVICE_CLASS_PREFIX;
		String classSuffix = CostConstants.SERVICE_CLASS_SUFFIX;
		String packageName = config.getServicePackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);

		//模块名
		moduleName = CostConstants.SERVICE_IMPL_MODULE_NAME;
		templateName = CostConstants.SERVICE_IMPL_TEMPLATE_NAME;
		classPrefix = CostConstants.SERVICE_IMPL_CLASS_PREFIX;
		classSuffix = CostConstants.SERVICE_IMPL_CLASS_SUFFIX;
		packageName = config.getServicePackageName().replace(".", SEPARATOR)+SEPARATOR+"impl"+SEPARATOR;
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);
	}

	/**
	 * 生成mapper文件
	 */
	@Override
	public void genRepositoryClass(ClassInfo classInfo) {
		//模块名
		String moduleName = CostConstants.MAPPER_MODULE_NAME;
		String templateName = CostConstants.MAPPER_TEMPLATE_NAME;
		String classPrefix = CostConstants.MAPPER_CLASS_PREFIX;
		String classSuffix = CostConstants.MAPPER_CLASS_SUFFIX;
		String packageName = config.getMapperPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);
	}

	/**
	 * 生成mapper.xml
	 */
	@Override
	public void genRepositoryXml(ClassInfo classInfo) {
		String moduleName = CostConstants.MAPPER_XML_MODULE_NAME;
		String templateName = CostConstants.MAPPER_XML_TEMPLATE_NAME;
		String classPrefix = CostConstants.MAPPER_XML_CLASS_PREFIX;
		String classSuffix = CostConstants.MAPPER_XML_CLASS_SUFFIX;
		genResourcesFile(classInfo, templateName, moduleName, classPrefix, classSuffix);
	}

	/**
	 * 生成实体
	 */
	@Override
	public void genEntity(ClassInfo classInfo) {
		//模块名
		String moduleName = CostConstants.ENTITY_MODULE_NAME;
		String templateName = CostConstants.ENTITY_TEMPLATE_NAME;
		String classPrefix = CostConstants.ENTITY_CLASS_PREFIX;
		String classSuffix = CostConstants.ENTITY_CLASS_SUFFIX;
		String packageName = config.getEntityPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);
	}

	/**
	 * 生成service层的表单
	 */
	@Override
	public void genServiceForm(ClassInfo classInfo) {
		String moduleName = CostConstants.ADD_FORM_MODULE_NAME;
		String templateName = CostConstants.ADD_FORM_TEMPLATE_NAME;
		String classPrefix = CostConstants.ADD_FORM_CLASS_PREFIX;
		String classSuffix = CostConstants.ADD_FORM_CLASS_SUFFIX;
		String packageName = config.getFormPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);

		moduleName = CostConstants.QUERY_FORM_MODULE_NAME;
		templateName = CostConstants.QUERY_FORM_TEMPLATE_NAME;
		classPrefix = CostConstants.QUERY_FORM_CLASS_PREFIX;
		classSuffix = CostConstants.QUERY_FORM_CLASS_SUFFIX;
		packageName = config.getFormPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);

		moduleName = CostConstants.IMPORT_FORM_MODULE_NAME;
		templateName = CostConstants.IMPORT_FORM_TEMPLATE_NAME;
		classPrefix = CostConstants.IMPORT_FORM_CLASS_PREFIX;
		classSuffix = CostConstants.IMPORT_FORM_CLASS_SUFFIX;
		packageName = config.getFormPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);

		moduleName = CostConstants.DEl_FORM_MODULE_NAME;
		templateName = CostConstants.DEl_FORM_TEMPLATE_NAME;
		classPrefix = CostConstants.DEl_FORM_CLASS_PREFIX;
		classSuffix = CostConstants.DEl_FORM_CLASS_SUFFIX;
		packageName = config.getFormPackageName().replace(".", SEPARATOR);
		genClass(classInfo, templateName, moduleName, classPrefix, classSuffix, packageName);
	}


}
